module.exports = function (app, api_prefix = '/api/mock') {
    const path = require("path");
    const fs = require("fs");
    const multer = require('multer'); // 支持 multipart/form-data 类型
    const upload = multer();

    const log4js = require('log4js');
    const yaml = require("yaml");
    const wildcard = require("wildcard");


    const logger = log4js.getLogger('mock');
    log4js.getLogger().debug(`Startup mock api_prefix=${api_prefix}`);

    const image_generator_dir = path.join(__dirname, "public/image_generator");
    
    const resolveCode = function(doc, node) {
        return eval(`(${node.strValue})`);
    };
    
    const yamlOptions = {
        customTags: [
            { tag: "!fn", class: Function, resolve: resolveCode },
            { tag: "!re", class: RegExp, resolve: resolveCode },
        ]
    };

    // cgi, common gateway interface 通用网关接口
    // api, application programming  interface 应用程序接口
    app.use(api_prefix, upload.any(), function (req, res, next) {
        var params = req.method == "GET" ? req.query : req.body;
        var headers = req.headers;
        // res.set({
        //     'Content-Type': 'text/plain',
        // });
        try {
            let cfgStr = fs.readFileSync("cfg/mock/mock.yml", { encoding: "utf-8"});
            let cfgData = yaml.parse(cfgStr, yamlOptions);
            let template;
            var match_path = req.url[0] == "/" ? req.url : (req.path + new URL(req.url).search);
            for (let key in cfgData) {
                if (wildcard(key, match_path)) {
                    template = cfgData[key];
                    break;
                }
            }
            if (template) {
                let result = require("mockjs").mock(template);
                sendResponse(req, res, 200, result);
            } else {
                sendResponse(req, res, 404, 'Not Found');
            }
        } catch (err) {
            sendResponse(req, res, 500, 'Internal Server Error! ' + err);
            return;
        };
    });

    function sendResponse(req, res, status_code, msg) {
        // 以 json 对象返回
        res.set({
            'Content-Type': 'application/json',
        });
        // 把错误统一封装
        if (typeof msg === "string" && status_code != 200) {
            msg = { msg: msg, code: -1 };
        }
        var params = req.method == "GET" ? req.query : req.body;
        let max_log_msg = 100;
        let log_msg = JSON.stringify(msg);
        log_msg = log_msg.length > max_log_msg ? (log_msg.substr(0, max_log_msg) + "...") : log_msg;
        let logger_fn = logger.debug;
        if (status_code == 200) {
            logger_fn = logger.debug;
        } else if (Math.floor(status_code / 100) == 2) {
            logger_fn = logger.info;
        } else {
            logger_fn = logger.error;
        }
        logger_fn.call(logger, `[${req.method}] ${req.path} ${JSON.stringify(params)} ${JSON.stringify(req.headers)}=> [${status_code}] ${log_msg}`);

        res.status(status_code).send(msg);
    }
}
